from datetime import datetime
from typing import Callable

from definition.conversation_model import ConversationModel, Utterance, Node, FlowNode, Action, HangUpAction, \
    HumanTransferAction, ReturnAction, JumperAction


class ChatRecord:
    def __init__(self, speaker: str, text: str):
        self.speaker = speaker
        self.text = text
        self.speak_time: datetime = datetime.now()


class ConversationInstance:
    def __init__(self, conversation_model: ConversationModel, interactor: str):
        self.conversation_model = conversation_model
        self.interactor = interactor
        self.start_time: datetime = None
        self.end_time: datetime = None
        self.flow_labels: list[str] = []
        self.qa_labels: list[str] = []
        self.intention_grade_label: str | None = None
        self.chat_records: list[ChatRecord] = []
        self.__speaking_listeners: list[Callable] = []
        self.__current_node: Node = conversation_model.scenes[0].nodes[0]

    def get_current_node(self) -> Node:
        return self.__current_node

    def start(self):
        self.start_time = datetime.now()
        self.execute()

    def activate_node(self, node: Node):
        self.__current_node = node

    def execute(self):
        utterances = self.__current_node.get_utterances()
        # 为了避免死循环，在执行节点的时候不会执行动作
        [self.__say(utterance, False) for utterance in utterances]

    def receive_message(self, message: str):
        self.chat_records.append(ChatRecord(message, self.interactor))
        # ## 将文本切分成几段
        # nlp = spacy.load('zh_core_web_sm')
        # doc = nlp(message)
        # for sent in doc.sents:
        #     print(sent.text)
        ## 进行分支处理
        if isinstance(self.__current_node, FlowNode):
            if self.__current_node.enable_branch_condition:
                # 如果当前节点开启了分支
                branches = [*self.__current_node.branches]
                if self.__current_node.included_node:
                    branches.extend(self.__current_node.included_node.branches)

                branch = next((branch for branch in branches if branch.intent.match(message)), None)
                if branch:
                    self.activate_node(branch.to_node)
                    self.execute()
                    return
            else:
                print("出错，没有开始分支的节点不应该停留")
        else:
            print("出错，不是流程节点不应该停留")

        ## 找QA
        qa = next((qa for qa in self.conversation_model.global_setting.qa_settings if qa.intent.match(message)), None)
        if qa:
            utterance = qa.get_utterance()
            self.__say(utterance, True)
        ## 无法处理

    def register_speaking_listener(self, listener):
        self.__speaking_listeners.append(listener)

    def __say(self, utterance: Utterance, do_action: bool = True):
        self.chat_records.append(ChatRecord(utterance.text, "AI"))
        [speaking_listener(utterance) for speaking_listener in self.__speaking_listeners]

        if utterance.action and do_action:
            self.__do_action()

    def __do_action(self, action: Action):
        if not action:
            return

        if isinstance(action, HangUpAction):
            print("挂机")
        elif isinstance(action, HumanTransferAction):
            print("转人工")
        elif isinstance(action, ReturnAction):
            self.execute()
        elif isinstance(action, JumperAction):
            self.activate_node(action.to_node)
            self.execute()


class FlowEngine:
    def __init__(self, conversation_model: ConversationModel, interactor: str):
        self.interactor = interactor
        self.conversation_model = conversation_model

    def new_instance(self) -> ConversationInstance:
        conversation_instance = ConversationInstance(self.conversation_model, self.interactor)
        return conversation_instance
